#ifndef EXPRESSION_H_
#define EXPRESSION_H_
#include "Multitree.h"
#include <iostream> //We want to be able to output expression to output.
#include <string>
namespace SymCe{
	//This class is the one user sees.
	class Expression{
		private:
			Multitree * tree;
		public:
			Expression(std::string variablename); //If the string is an identifier, make it variable name.
			//or we should maybe use some parser to make whole expression? No.
			Expression(char * constantname, Number value); //And what about real numbers? What will we do?
			//Expression(Integer);
			Expression(char * variablename);
			Expression(int i);
			Expression(double d);
			Expression(Number);
			Expression(const Expression & ex);
			Expression();
			Expression(OperatorType op, bool inv, Multitree * left, Multitree * right);
			Expression(FunctionType fn, Multitree * arg);
			~Expression();
			Expression & operator=(const Expression & ex);
			Expression operator+(const Expression &) const;
			Expression operator-(const Expression &) const;
			Expression operator*(const Expression &) const;
			Expression operator/(const Expression &) const;
			Expression operator^(const Expression &) const;

			/*
			Expression & operator=(const Number & ex);
			Expression operator+(const Number &) const;
			Expression operator-(const Number &) const;
			Expression operator*(const Number &) const;
			Expression operator/(const Number &) const;
			Expression operator^(const Number &) const;
			*/


			friend std::ostream & operator<<(std::ostream & stream, const Expression & ex);
			std::ostream & output(std::ostream & stream);
			std::ostream & output(std::ostream & stream) const;
			Expression tan();
			Expression ln();
			Expression sin();
			Expression cos();
			Expression reduce(); //Is it good name?
			Expression diff(char * variable);
			Expression diff(Expression & variable);
			Expression replace_variable(char * variable, Expression & ex);
			Expression replace_variable(Expression & variable, Expression & ex);
			Expression expand();
			Expression taylor(Number center, unsigned short int terms, char * variable);
			Expression taylor(Number center, unsigned short int terms, Expression & variable);

	};

	std::ostream & operator<<(std::ostream & stream, Expression & ex);
	std::ostream & operator<<(std::ostream & stream, Expression const & ex);
	/*Expression operator+(Number & number, Expression & ex);
	Expression operator-(Number & number, Expression & ex);
	Expression operator*(Number & number, Expression & ex);
	Expression operator/(Number & number, Expression & ex);*/



	//Functions
	Expression tan(Expression & ex);
	Expression ln(Expression & ex);
	Expression sin(Expression & ex);
	Expression cos(Expression & ex);
}
#endif /*EXPRESSION_H_*/
